"""
中间件配置模块
实现各种全局中间件的注册和配置
"""
from fastapi import FastAPI, Request, Response
from starlette.middleware.base import BaseHTTPMiddleware
import time
import uuid
from typing import Callable, List

from pkg.settings.config import settings
from pkg.middlewares.auth_middleware import AuthenticationMiddleware


class RequestLogMiddleware(BaseHTTPMiddleware):
    """
    请求日志中间件，记录每个请求的方法、路径、状态码和响应时间
    """
    
    async def dispatch(self, request: Request, call_next: Callable) -> Response:
        request_id = str(uuid.uuid4())
        request.state.request_id = request_id
        
        # 记录请求开始信息
        start_time = time.time()
        
        
        # 处理请求
        try:
            response = await call_next(request)
            
            # 记录请求完成信息
            process_time = time.time() - start_time
            response.headers["X-Request-ID"] = request_id
            response.headers["X-Process-Time"] = str(process_time)
            
           
            return response
        except Exception as e:
            # 记录异常信息
            process_time = time.time() - start_time
            raise


class SecurityHeadersMiddleware(BaseHTTPMiddleware):
    """
    安全头中间件，添加常见的安全HTTP头
    """
    
    async def dispatch(self, request: Request, call_next: Callable) -> Response:
        response = await call_next(request)
        
        # 添加安全头
        response.headers["X-Content-Type-Options"] = "nosniff"
        response.headers["X-Frame-Options"] = "DENY"
        response.headers["X-XSS-Protection"] = "1; mode=block"
        response.headers["Strict-Transport-Security"] = "max-age=31536000; includeSubDomains"
        
        return response


def setup_middlewares(app: FastAPI) -> None:
    """
    设置应用的中间件
    :param app: FastAPI应用实例
    """
    # 添加请求日志中间件
    app.add_middleware(RequestLogMiddleware)
    
    # 仅在生产环境添加安全头中间件
    # if not settings.DEBUG:
    #     app.add_middleware(SecurityHeadersMiddleware)
    
    # 添加认证中间件
    # 定义不需要认证的路径列表
    exclude_paths: List[str] = [
        "/auth/login",
        "/auth/refresh",
        "/auth/verify",
        "/static/",
    ]
    
    # 根据配置决定是否启用全局认证中间件
    if getattr(settings, 'AUTH_REQUIRED', False):
        app.add_middleware(AuthenticationMiddleware, exclude_paths=exclude_paths)
